package com.photoeditor.demo.util;

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.os.Build;

import com.android.av.edit.VideoFilterDevice;
import com.android.gpuimage.GPUImageFilter;
import com.android.gpuimage.GPUImageFilterGroup;
import com.android.gpuimage.GPUImageOESFilter;
import com.android.videolib.MediaCodecHelper;
import com.android.videolib.VideoCooker;
import com.photoeditor.R;
import com.photoeditor.demo.statistics.StatisticsUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/9/18 0018.
 */

public class Gif2VideoUtils {

    // 多视频合成默认720p
    public static int VIDEO_OUTPUT_H = 720;

    // gif合成视频默认1080p,即高度固定为1080，宽度根据比例缩放
    public static int GIF_VIDEO_OUTPUT_H = 1080;
    public static boolean sSuppoft1080 = true;

    /**
     * 高比特率输出，合成的视频约为2.0MB/s
     */
    public static final int BITRATE_HIGH = 20000000;
    public static final int BITRATE_DEFAULT = -1;

    static {
        // 4.4如果使用1080p会出现花屏
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            GIF_VIDEO_OUTPUT_H = 720;
        }
    }

    /**
     * gif合成视屏 使用空视屏
     * @param destFile
     * @param filters
     * @param outputWidth
     * @param outputHeight
     * @param frame
     * @param duration
     * @param resultCallback
     */
    public static void gif2Video(File destFile, List<GPUImageFilter> filters, int outputWidth, int outputHeight, float frame, int duration, final VideoFilterDevice.ResultCallback resultCallback) {
        gif2Video(destFile, filters, outputWidth, outputHeight, frame, BITRATE_DEFAULT, duration, resultCallback);
    }

    public static void gif2Video(File destFile, GPUImageFilter filter, int outputWidth, int outputHeight, float frame, int duration, final VideoFilterDevice.ResultCallback resultCallback) {
        List<GPUImageFilter> filters = new ArrayList<>();
        filters.add(filter);
        gif2Video(destFile, filters, outputWidth, outputHeight, frame, BITRATE_DEFAULT, duration, resultCallback);
    }


    /**
     * gif合成视屏 使用空视屏
     * @param destFile
     * @param filters
     * @param outputWidth
     * @param outputHeight
     * @param frame
     * @param minBitrate 生成的视频的最小比特率，无特殊需要使用{@link #BITRATE_DEFAULT}即可
     * @param duration
     * @param resultCallback
     */
    public static void gif2Video(File destFile, List<GPUImageFilter> filters, int outputWidth, int outputHeight, float frame, int minBitrate, int duration, final VideoFilterDevice.ResultCallback resultCallback) {

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            minBitrate = BITRATE_DEFAULT;
        }
        final String emptyVideoPath = FileUtil.getBasicVideoPath() + File.separator + System.currentTimeMillis() + ".mp4";

        if (frame > 30) {
            if(!new File(FileUtil.BASIC_VIDEO_50_FILE_PATH).exists()) {
                FileUtil.copyRawToFileSystem(R.raw.basic_video_50_no_audio, FileUtil.BASIC_VIDEO_50_FILE_PATH);
            }
            VideoCooker.makeEmptyVideo(FileUtil.BASIC_VIDEO_50_FILE_PATH, emptyVideoPath,
                    verifyVideoOutPutSize(outputWidth),
                    verifyVideoOutPutSize(outputHeight),
                    140,
                    duration);
        } else {
            if(!new File(FileUtil.BASIC_VIDEO_30_FILE_PATH).exists()) {
                FileUtil.copyRawToFileSystem(R.raw.basic_video_30_no_audio, FileUtil.BASIC_VIDEO_30_FILE_PATH);
            }
            VideoCooker.makeEmptyVideo(FileUtil.BASIC_VIDEO_30_FILE_PATH, emptyVideoPath,
                    verifyVideoOutPutSize(outputWidth),
                    verifyVideoOutPutSize(outputHeight),
                    170,
                    duration);
        }

        gif2Video(new File(emptyVideoPath), minBitrate, true, destFile, filters, resultCallback);
    }

    /**
     * gif合成视屏使用现有视屏
     * @param srcFile
     * @param destFile
     * @param filters
     * @param resultCallback
     */
    public static void gif2Video(final File srcFile, final boolean deleteSrc, File destFile, List<GPUImageFilter> filters, final VideoFilterDevice.ResultCallback resultCallback) {
        gif2Video(srcFile, BITRATE_DEFAULT, deleteSrc, destFile, filters, resultCallback);
    }

    /**
     * gif合成视屏使用现有视屏
     * @param srcFile
     * @param minBitrate 生成的视频的最小比特率，无特殊需要使用{@link #BITRATE_DEFAULT}即可
     * @param destFile
     * @param filters
     * @param resultCallback
     */
    public static void gif2Video(final File srcFile, int minBitrate, final boolean deleteSrc, File destFile, List<GPUImageFilter> filters, final VideoFilterDevice.ResultCallback resultCallback) {
        GPUImageFilterGroup group = new GPUImageFilterGroup();
        group.addFilter(new GPUImageOESFilter());
        group.addFilter(filters);

        int degrees = 0;
        int bitRate = 0;
        final int width;
        final int height;
        if (!srcFile.exists()) {
            if(resultCallback != null) {
//                StatisticsUtils.statisticsMakeVideoResult(false);
                StatisticsUtils.statisticsMakeVideoError("2gif empty mp4 dont exist", 0, 0);
                resultCallback.onError();
            }
            return;
        }
        MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever();
        retrieverSrc.setDataSource(srcFile.getAbsolutePath());
        String degreesString = retrieverSrc.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
        if (degreesString != null) {
            degrees = Integer.valueOf(degreesString);
        }
        String bitrateString = retrieverSrc.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_BITRATE);
        if (bitrateString != null) {
            bitRate = Integer.valueOf(bitrateString);
        }
        if (bitRate < minBitrate) {
            bitRate = minBitrate;
        }
        String widthString = retrieverSrc.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
        width = Integer.valueOf(widthString);
        String heightString = retrieverSrc.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
        height = Integer.valueOf(heightString);

        VideoFilterDevice videoDevice = null;
        try {
            videoDevice = new VideoFilterDevice(srcFile, destFile, group, width, height, degrees, bitRate, null, new VideoFilterDevice.ResultCallback() {
                @Override
                public void onError() {
//                    StatisticsUtils.statisticsMakeVideoResult(false);
                    StatisticsUtils.statisticsMakeVideoError("videofilterdevice error", width, height);
                    if(deleteSrc && srcFile.exists()) {
                        srcFile.delete();
                    }
                    if(resultCallback != null) {
                        resultCallback.onError();
                    }
                }

                @Override
                public void onSuccess(File outputFile) {
//                    StatisticsUtils.statisticsMakeVideoResult(true);
                    if(deleteSrc && srcFile.exists()) {
                        srcFile.delete();
                    }
                    if(resultCallback != null) {
                        resultCallback.onSuccess(outputFile);
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
            if(resultCallback != null) {
                resultCallback.onError();
            }
        }
        videoDevice.start();
    }


    //转变为偶数
    public static int turnSizeToEven(int size) {
        if (size % 2 == 1) {
            return size - 1;
        }
        return size;
    }

    /**
     * 生成视频大小转成4的整数倍，解决mate9 7.0系统生成添加gif后，保存视频crash(PE-199)
     * @param size
     * @return
     */
    public static int verifyVideoOutPutSize(int size) {
        int ret;
        int mod = size % 4;
        if (mod < 3) {
            ret = size - mod;
        } else {
            ret = size + (4 - mod);
        }
        return ret;
    }

    public static int[] getVideoOutputSize(int orgWidth, int orgHeight) {
        if (orgHeight < GIF_VIDEO_OUTPUT_H) {
            orgHeight = verifyVideoOutPutSize(orgHeight);
            orgWidth = MediaCodecHelper.getInstance().getSupportVideoWidth(orgWidth, orgHeight);
            return new int[]{orgWidth, orgHeight};
        }
        int width;
        int height;
        if (!sSuppoft1080) {
            if (orgHeight < orgWidth || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                width = GIF_VIDEO_OUTPUT_H;
                height = (width * orgHeight / orgWidth);
                height = MediaCodecHelper.getInstance().getSupportVideoHeight(width, height);
            } else {
                height = GIF_VIDEO_OUTPUT_H;
                width = (height * orgWidth / orgHeight);
                width = MediaCodecHelper.getInstance().getSupportVideoWidth(width, height);
            }
        } else {
            height = GIF_VIDEO_OUTPUT_H;
            width = (height * orgWidth / orgHeight);
            width = MediaCodecHelper.getInstance().getSupportVideoWidth(width, height);
        }

        return new int[]{width, height};
    }

    public static void checkIsSupport1080P() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            // 5.0 5.1部分机型执行下面方法会crash，因此统一设置为低分辨
            // 4.4的手机调用encoder.release()会出现“signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------”的异常
            sSuppoft1080 = false;
            GIF_VIDEO_OUTPUT_H = 720;
            return;
        }

        int width = 810;
        int height = 1080;
        MediaCodec encoder = null;
        try {
            MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
            format.setInteger(MediaFormat.KEY_WIDTH, width);
            format.setInteger(MediaFormat.KEY_HEIGHT, height);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT, 0x7F000789
                /*MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface*/);
            format.setInteger(MediaFormat.KEY_BIT_RATE, 2 * 1000 * 1000);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 3);
            encoder = MediaCodec.createEncoderByType("video/avc");
            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            encoder.start();
        } catch(Exception tr) {
            sSuppoft1080 = false;
            GIF_VIDEO_OUTPUT_H = 720;
        }
        if (encoder != null) {
            encoder.release();
        }
    }
}
